package org.nnsoft.guice.autobind.scanner.asm; /* * Copyright 2012 The 99 Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import static java.util.Collections.unmodifiableList; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; import static org.objectweb.asm.ClassReader.SKIP_CODE; import static org.objectweb.asm.ClassReader.SKIP_DEBUG; import static org.objectweb.asm.ClassReader.SKIP_FRAMES; import static org.objectweb.asm.Opcodes.ASM4; import java.lang.annotation.Annotation; import java.util.HashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.logging.Logger; import org.nnsoft.guice.autobind.scanner.features.ScannerFeature; import org.objectweb.asm.AnnotationVisitor; import org.objectweb.asm.ClassVisitor; /** * Visitor implementation to collect field annotation information from class. */ final class AnnotationCollector extends ClassVisitor { public static final int ASM_FLAGS = SKIP_CODE | SKIP_DEBUG | SKIP_FRAMES; private final Logger _logger = getLogger( getClass().getName() ); private String _name; private Class<?> _class; private boolean _ignore; private final Map<String, Annotation> _annotations; private final List<ScannerFeature> _features; public AnnotationCollector() { super( ASM4 ); _features = new LinkedList<ScannerFeature>(); _annotations = new HashMap<String, Annotation>(); } public void addScannerFeature( ScannerFeature listener ) { _features.add( listener ); } public void removerScannerFeature( ScannerFeature listener ) { _features.remove( listener ); } public List<ScannerFeature> getScannerFeatures() { return unmodifiableList( _features ); } public void destroy() { _annotations.clear(); _class = null; _features.clear(); } @Override public void visit( int version, int access, String name, String signature, String superName, String[] interfaces ) { _name = name.replace( '/', '.' ); for ( String interf : interfaces ) { if ( interf.equals( "java/lang/annotation/Annotation" ) ) { _ignore = true; return; } } } @SuppressWarnings( "unchecked" ) public AnnotationVisitor visitAnnotation( String sig, boolean visible ) { if ( _ignore ) { return null; } String annotationClassStr = sig.replace( '/', '.' ).substring( 1, sig.length() - 1 ); if ( _class == null ) { try { _class = Thread.currentThread().getContextClassLoader().loadClass( _name ); } catch ( ClassNotFoundException e ) { _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e ); return null; } } try { Class<Annotation> annotationClass = (Class<Annotation>) getClass().getClassLoader().loadClass( annotationClassStr ); Annotation annotation = _class.getAnnotation( annotationClass ); _annotations.put( annotationClassStr, annotation ); } catch ( ClassNotFoundException e ) { e.printStackTrace(); _logger.log( WARNING, "Failure while visitAnnotation. Class could not be loaded.", e ); } return null; } @SuppressWarnings( "unchecked" ) @Override public void visitEnd() { if ( !_ignore && _annotations.size() > 0 && !_annotations.containsKey( "javax.enterprise.inject.Alternative" ) ) { for ( ScannerFeature listener : _features ) { listener.found( (Class<Object>) _class, _annotations ); } } _name = null; _class = null; _ignore = false; _annotations.clear(); } }